package com.lyrcsoft.rxjava1x.operators.convert;

import lombok.extern.slf4j.Slf4j;
import rx.Observable;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

import java.util.concurrent.TimeUnit;

/**
 * @author fujc2dev@126.com
 * @date 2024-11-20
 */
@Slf4j


public class RxJavaSwitchFlatMapDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Using flatMap:");
        Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
                .flatMap(new Func1<Integer, Observable<?>>() {
                    @Override
                    public Observable<?> call(Integer integer) {
                        // 模拟每个请求有一定的延迟
                        return Observable.just(integer)
                                .doOnNext(i -> System.out.println("flatMap Emitting: " + i))
                                .delay(100 * integer, java.util.concurrent.TimeUnit.MILLISECONDS);
                    }
                })
                .subscribe(
                        System.out::println,
                        Throwable::printStackTrace,
                        () -> System.out.println("flatMap Completed")
                );

        Thread.sleep(2000);

        System.out.println("\nUsing switchMap:");
        Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
                .switchMap(new Func1<Integer, Observable<?>>() {
                    @Override
                    public Observable<?> call(Integer integer) {
                        // 模拟每个请求有一定的延迟
                        return Observable.just(integer)
                                .doOnNext(i -> System.out.println("switchMap Emitting: " + i))
                                .delay(100 * integer, java.util.concurrent.TimeUnit.MILLISECONDS);
                    }
                })
                .subscribe(
                        System.out::println,
                        Throwable::printStackTrace,
                        () -> System.out.println("switchMap Completed")
                );

        Thread.sleep(2000);
    }
}

class SearchApi {
    public static Observable<String> search(String query) {
        // 模拟搜索API，每次返回结果需要 500 毫秒
        return Observable.just("Result for: " + query)
                .delay(500, TimeUnit.MILLISECONDS);
    }
}

class InputSimulator {
    public static Observable<String> simulateInput() {
        // 模拟用户连续输入 "Rx"、"RxJ"、"RxJava"
        return Observable.just("Rx", "RxJ", "RxJava")
                .concatMap(input -> Observable.just(input).delay(300, TimeUnit.MILLISECONDS));
    }
}

class SimpleSwitchMapExample {
    public static void main(String[] args) throws InterruptedException {
        // 获取模拟输入
        Observable<String> inputObservable = InputSimulator.simulateInput();

        inputObservable
                .switchMap(query ->
                        SearchApi.search(query)
                                .subscribeOn(Schedulers.io()) // 搜索在IO线程执行
                )
                .subscribe(result -> {
                    System.out.println("Search Result: " + result);
                });

        // 等待程序完成
        Thread.sleep(2000);
    }
}

/**
 * 搞半天，大概明白这个flatMap与switchMap的区别。switchMap 发射了10次，在用户没有收到之前，新的发射被发出后，旧的发射被取消。
 * 案例：实时搜索。当用户在搜索框中输入关键词时，每次输入新字符都会触发一个搜索请求。如果用户快速输入多个字符，
 * 旧的搜索请求就会被取消，只保留最新的搜索结果。
 * 通过与AI进行拉回拉扯，SimpleSwitchMapExample例子：
 * 1. 模拟用户连续输入 "Rx"、"RxJ"、"RxJava"，输入间隔时间是300ms。
 * 2. 每次输入后，调用 SearchApi.search() 方法进行搜索，处理间隔是500ms，输入时间比处理时间快
 * 3. 使用 switchMap() 操作符，将每个输入转换为一个 Observable，然后使用 delay() 操作符模拟搜索延迟。
 * 4. 当新的输入来临时，旧的搜索请求会被取消，只保留最新的搜索结果。
 */
